package org.angelica.utils.http;

import com.google.common.collect.Maps;
import org.angelica.utils.common.ToolUtil;
import org.angelica.utils.id.IdGeneratorUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * http 请求相关工具类
 * @author aizhimin
 *
 */
public class HttpUtil {
	private static Logger logger = LoggerFactory.getLogger(HttpUtil.class);
	
	/**
	 * 获取HttpServletRequest
	 * @return
	 */
	public static HttpServletRequest getHttpServletRequest() {
		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
	}
	
	/**
	 * 获取request中的所有参数，并用&=拼接
	 * @param request
	 * @return
	 */
	public static String getRequestParameters(HttpServletRequest request) {
		StringBuilder params = new StringBuilder();
		Enumeration<String> enu = getHttpServletRequest().getParameterNames();
		while(enu.hasMoreElements()){
			String paraName = enu.nextElement(); 
			if(params.length() == 0) {
				params.append(paraName+"="+request.getParameter(paraName));
			}else{
				params.append("&"+paraName+"="+request.getParameter(paraName));
			}
		}
		return params.toString();
	}
	
	/**
	 * 获取客户端真实IP地址
	 * 
	 * 使用Nginx等反向代理软件， 则不能通过request.getRemoteAddr()获取IP地址
	 * 如果使用了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP地址，X-Forwarded-For中第一个非unknown的有效IP字符串，则为真实IP地址
	 */
	public static String getIpAddr(HttpServletRequest request) {
    	String ip = null;
        try {
            ip = request.getHeader("x-forwarded-for");


            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }

			if(StringUtils.isNotEmpty(ip) && !"unknown".equalsIgnoreCase(ip)){
				//多次反向代理后会有多个ip值，第一个ip才是真实ip
				int index = ip.indexOf(",");
				if(index != -1){
					return ip.substring(0,index);
				}else{
					return ip;
				}
			}
        } catch (Exception e) {
        	logger.error("HttpUtil ERROR ", e);
        }
        
        return ip;
    }

	/**
	 * 获取客户端信息
	 * @return
	 */
	public static String getUserAgent(HttpServletRequest request){
		return request.getHeader("User-Agent");
	}

	/**
	 * 获取重要的请求头信息
	 * @param request
	 * @return
	 */
	public static Map<String,String> getHeaderMap(HttpServletRequest request){
		Map<String,String> headerMap = Maps.newHashMap();
		headerMap.put("user-agent",request.getHeader("user-agent"));
		headerMap.put("sign",request.getHeader("sign"));
		headerMap.put("timestamp",request.getHeader("timestamp"));
		headerMap.put("nonce",request.getHeader("nonce"));
		headerMap.put("authorization",request.getHeader("authorization"));
		return headerMap;
	}

	/**
	 * 获取请求参数
	 * @param request
	 * @return
	 */
	public static Map<String,String> getParamMap(HttpServletRequest request){
		Map<String,String> paramMap = Maps.newHashMap();
		Enumeration<String> enu = request.getParameterNames();
		while(enu.hasMoreElements()) {
			String paramName = enu.nextElement();
			paramMap.put(paramName, request.getParameter(paramName));
		}
		return paramMap;
	}

	/**
	 * 构建请求头：时间戳 + 随机数 + 参数签名
	 * @param appid
	 * @param appSecret
	 * @param paramMap
	 * @return
	 */
	public static Map<String,String> buildRequestHeader(String appid, String appSecret, Map<String,String> paramMap) {
		String timestamp = String.valueOf(System.currentTimeMillis());
		String nonce = IdGeneratorUtil.getRandomUuid();
		paramMap.put("timestamp", timestamp);
		paramMap.put("nonce", nonce);
		String sign = ToolUtil.sign(appid, appSecret, paramMap);
		Map<String,String> headerMap = new HashMap<>(3);
		headerMap.put("timestamp", timestamp);
		headerMap.put("nonce", nonce);
		headerMap.put("sign", sign);
		return headerMap;
	}

}
